package org.jaaksi.customviewdemo.roundview

import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.drawable.GradientDrawable
import android.graphics.drawable.RippleDrawable
import android.os.Build
import android.util.AttributeSet
import android.view.View
import androidx.core.view.doOnPreDraw
import org.jaaksi.customviewdemo.R

class RoundViewDelegate(private val view: View, attrs: AttributeSet?) {
    private var shouldSetBd = true

    var backgroundColor = Color.TRANSPARENT
        set(value) {
            field = value
            setBackgroundDrawable()
        }

    private var gradientColors = intArrayOf()
    private var orientation: GradientDrawable.Orientation = GradientDrawable.Orientation.LEFT_RIGHT

    var strokeWidth = 0
        set(value) {
            field = value
            setBackgroundDrawable()
        }

    var strokeColor = Color.TRANSPARENT
        set(value) {
            field = value
            setBackgroundDrawable()
        }

    var rippleEnable = false
        set(value) {
            field = value
            setBackgroundDrawable()
        }

    var rippleColor = Color.WHITE
        set(value) {
            field = value
            setBackgroundDrawable()
        }

    /**
     * 对应Ripple的mask，用于对无背景的View添加Ripple，只需要设置cornerRadius和rippleColor即可
     * isRippleEnable必须为true且rippleColor!=Color.transparent才有效
     */
    var asMask = false
        set(value) {
            field = value
            setBackgroundDrawable()
        }

    // 圆角是否为半圆，仅在view绘制前有效。如果要动态调整，可以使用cornerRadius
    var halfRoundCorner = false
        set(value) {
            field = value
            if (view !is IRoundViewDelegate) {
                view.doOnPreDraw {
                    checkAndSetBackground()
                }
            }
        }

    var cornerRadius = 0f
        private set
    var topLeftRadius = 0f
        private set
    var topRightRadius = 0f
        private set
    var bottomLeftRadius = 0f
        private set
    var bottomRightRadius = 0f
        private set

    private val radiusArr = FloatArray(8)
    private val gdBackground = GradientDrawable()

    init {
        obtainAttributes(attrs)
    }

    private fun obtainAttributes(attrs: AttributeSet?) {
        attrs ?: return
        shouldSetBd = false
        val attr = view.context.obtainStyledAttributes(attrs, R.styleable.DJRoundView)
        backgroundColor =
            attr.getColor(R.styleable.DJRoundView_rv_backgroundColor, Color.TRANSPARENT)
        val startColor =
            attr.getColor(R.styleable.DJRoundView_rv_startColor, Color.TRANSPARENT)
        val endColor =
            attr.getColor(R.styleable.DJRoundView_rv_endColor, Color.TRANSPARENT)
        if (startColor != Color.TRANSPARENT && endColor != Color.TRANSPARENT) {
            gradientColors = intArrayOf(startColor, endColor)
        }
        rippleColor = attr.getColor(R.styleable.DJRoundView_rv_rippleColor, Color.WHITE)
        rippleEnable = rippleColor != Color.TRANSPARENT && attr.getBoolean(
            R.styleable.DJRoundView_rv_rippleEnable,
            false
        )
        asMask = rippleEnable && attr.getBoolean(R.styleable.DJRoundView_rv_asMask, false)
        cornerRadius =
            attr.getDimension(R.styleable.DJRoundView_rv_radius, 0f)
        strokeWidth = attr.getDimensionPixelSize(R.styleable.DJRoundView_rv_strokeWidth, 0)
        strokeColor = attr.getColor(R.styleable.DJRoundView_rv_strokeColor, Color.TRANSPARENT)
        halfRoundCorner = attr.getBoolean(R.styleable.DJRoundView_rv_halfRoundCorner, false)
        topLeftRadius = attr.getDimension(R.styleable.DJRoundView_rv_topLeftRadius, 0f)
        topRightRadius = attr.getDimension(R.styleable.DJRoundView_rv_topRightRadius, 0f)
        bottomLeftRadius =
            attr.getDimension(R.styleable.DJRoundView_rv_bottomLeftRadius, 0f)
        bottomRightRadius =
            attr.getDimension(R.styleable.DJRoundView_rv_bottomRightRadius, 0f)
        attr.recycle()
        shouldSetBd = true
    }

    fun updateParams(block: RoundViewDelegate.() -> Unit) {
        // 避免每次执行setBgSelector
        shouldSetBd = false
        block()
        shouldSetBd = true
        setBackgroundDrawable()
    }

    fun setRadius(
        radius: Float = 0f,
        topLeftRadius: Float = 0f,
        topRightRadius: Float = 0f,
        bottomLeftRadius: Float = 0f,
        bottomRightRadius: Float = 0f,
    ) {
        this.cornerRadius = radius
        this.topLeftRadius = topLeftRadius
        this.topRightRadius = topRightRadius
        this.bottomLeftRadius = bottomLeftRadius
        this.bottomRightRadius = bottomRightRadius
        setBackgroundDrawable()
    }

    fun setGradient(
        colors: IntArray,
        orientation: GradientDrawable.Orientation = GradientDrawable.Orientation.LEFT_RIGHT
    ) {
        this.gradientColors = colors
        this.orientation = orientation
        setBackgroundDrawable()
    }

    // 仅供内部使用
    internal fun checkAndSetBackground() {
        if (halfRoundCorner) {
            setRadius(view.height / 2f)
        } else {
            setBackgroundDrawable()
        }
    }

    private fun updateDrawable() {
        gdBackground.let {
            if (gradientColors.isNotEmpty()) {
                it.orientation = this.orientation
                it.colors = gradientColors
            } else {
                it.setColor(backgroundColor)
            }
            it.setStroke(strokeWidth, strokeColor)
            it.shape = GradientDrawable.RECTANGLE
            if (cornerRadius > 0) {
                it.cornerRadius = cornerRadius
            } else {
                /**The corners are ordered top-left, top-right, bottom-right, bottom-left */
                /**The corners are ordered top-left, top-right, bottom-right, bottom-left */
                radiusArr[0] = topLeftRadius
                radiusArr[1] = topLeftRadius
                radiusArr[2] = topRightRadius
                radiusArr[3] = topRightRadius
                radiusArr[4] = bottomRightRadius
                radiusArr[5] = bottomRightRadius
                radiusArr[6] = bottomLeftRadius
                radiusArr[7] = bottomLeftRadius
                it.cornerRadii = radiusArr
            }
        }

    }

    private fun setBackgroundDrawable() {
        if (!shouldSetBd) return

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && rippleEnable && rippleColor != Color.TRANSPARENT) {
            updateDrawable()
            // 启用mask用作支持无背景的控件设置Ripple
            val rippleDrawable: RippleDrawable = if (asMask) {
                // 只需设置圆角即可
                gdBackground.setColor(Color.WHITE)
                RippleDrawable(ColorStateList.valueOf(rippleColor), null, gdBackground)
            } else {
                RippleDrawable(ColorStateList.valueOf(rippleColor), gdBackground, null)
            }
            view.background = rippleDrawable
        } else {
            updateDrawable()
            view.background = gdBackground
        }
    }
}